/*
* Conditions Of Use
*
* This software was developed by employees of the Sigmatrix(Beijing) Corporation.
* This software is provided by sigmatrix as a service and is expressly
* provided "AS IS."  Sigmatrix MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
* AND DATA ACCURACY.  Sigmatrix does not warrant or make any representations
* regarding the use of the software or the results thereof, including but
* not limited to the correctness, accuracy, reliability or usefulness of
* the software.
*
* Permission to use this software is contingent upon your acceptance
* of the terms of this agreement.
*
*/
package com.sigmatrix.h5.service.impl;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;

import org.apache.log4j.Logger;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONObject;
import com.sigmatrix.h5.components.FeignManager;
import com.sigmatrix.h5.dao.DisDealerAcctDao;
import com.sigmatrix.h5.dao.DisDealerDao;
import com.sigmatrix.h5.dao.DisRebateDetailDao;
import com.sigmatrix.h5.dao.EnterpriseDao;
import com.sigmatrix.h5.entity.DisDealer;
import com.sigmatrix.h5.entity.DisDealerAcct;
import com.sigmatrix.h5.entity.DisRebateAudit;
import com.sigmatrix.h5.entity.DisRebateDetail;
import com.sigmatrix.h5.entity.Enterprise;
import com.sigmatrix.h5.enums.CrmAcctType;
import com.sigmatrix.h5.enums.RebateTarget;
import com.sigmatrix.h5.enums.UserType;
import com.sigmatrix.h5.exception.MessageException;
import com.sigmatrix.h5.feign.args.WechatRedPacketDto;
import com.sigmatrix.h5.feign.mode.CoinDto;
import com.sigmatrix.h5.feign.mode.WechatRedPacketSendingResponse;
import com.sigmatrix.h5.service.DisRebateDetailService;
import com.sigmatrix.h5.utils.Assert;
import com.sigmatrix.h5.utils.CommonUtils;
import com.sigmatrix.h5.utils.Constants;
import com.sigmatrix.h5.utils.SessionUtils;
import com.sigmatrix.h5.web.Result;
import com.sigmatrix.h5.web.mode.AccumulatedRebate;
import com.sigmatrix.h5.web.mode.RebateList;
import com.sigmatrix.sc.jdbc.common.lang.Page;
import com.sigmatrix.sc.jdbc.common.service.ServiceImpl;

/**
 *@ClassName: DisRebateDetailServiceImpl
 *@Description: 
 *@author MH
 *@date 2017年8月11日 下午4:54:42
 */
@Service
public class DisRebateDetailServiceImpl extends ServiceImpl<DisRebateDetail,Integer> implements DisRebateDetailService{
	private Logger logger = Logger.getLogger(this.getClass());
	
	@Autowired
	private DisRebateDetailDao disRebateDetailDao;
	@Autowired
	private DisDealerAcctDao DisDealersAcctDao; 
	@Autowired
	private EnterpriseDao enterpriseDao;
	@Autowired
	private FeignManager feignClientManager;
	@Autowired
	private DisDealerDao distributionDealersDao;
	
	@Value("spring.application.name")
	private String seviceName;

	private final ReentrantLock lock = new ReentrantLock();

	@Override
	public Result<Object> selectRebateDetailsByDealerId(int dealerId, int pageNo, int pageSize) {
//		final DisRebateDetail vo = new DisRebateDetail();
//		vo.setDealerId(dealerId);
//		vo.setDealerType(SessionUtils.getDealerType());
//		//根据状态，创建时间倒序排序
//		Map<String,String> order = new HashMap<String,String>();
//		order.put("status", "desc");
//		order.put("rebateTime", "desc");
//		//查询列表
//		Page<DisRebateDetail> page = select(vo,order, pageNo, pageSize);
//		//初始化Result的分页信息
//		Result<Object> result = Result.ok(null);
//		//获取返利总和
//		AccumulatedRebate statistic = disRebateDetailDao.statistic(dealerId,SessionUtils.getDealerType());
//		JSONObject json = new JSONObject();
//		json.put("totalRebateAmount", statistic.getAccumulatedRebate().add(statistic.getAccumulatedWithDrawals()));
//		json.put("accumulatedRebate", statistic.getAccumulatedRebate());
//		json.put("accumulatedWithDrawals", statistic.getAccumulatedWithDrawals());
//		json.put("rebateDetail", page);
//		result.setData(json);
//		return result;
		throw new MessageException("未实现");
	}

	/**
	 * TODO 只针对中粮使用这个方法。
	 * 只能提个人零钱包中钱
	 */
	@Override
	@Transactional
	public Result<Object> sendWeChatRedPackage(DisDealerAcct acct, BigDecimal amount) {
		try {
			if(CommonUtils.isEmpty(amount)) return Result.error("提现金额不能为空");
			//单位转换，在返利系统单位是元，营销系单位是分
			amount = amount.multiply(new BigDecimal(100));
			//验证账号的正确性
			DisDealerAcct user = DisDealersAcctDao.findById(acct.getId());
			if(CommonUtils.isEmpty(user)) return Result.error("用户错误");
			if(!Short.valueOf("1").equals(user.getStatus())){
				return Result.error("用户不可用");
			}
			if(!acct.getOpenId().equals(user.getOpenId())) return Result.error("301","您的账号已在其他地方登录,请重新登录");

			//查询企业
			if(CommonUtils.isEmpty(user.getEnterpriseId())) return Result.error("无效的账号，没有关联企业");
			Enterprise enterprise = enterpriseDao.findById(user.getEnterpriseId());
			if(CommonUtils.isEmpty(enterprise)) return Result.error("没有查询到企业");
			//根据企业查询红包参数
			CoinDto coin = feignClientManager.findCoin(enterprise.getBasicModuleId());
			if(CommonUtils.isEmpty(coin)) return Result.error("没有查询到红包参数");
			//验证金额
			if(amount.compareTo(new BigDecimal(coin.getMaxAmount())) > 0){
				return Result.error("提现金额超出上限["+coin.getMaxAmount().doubleValue()/100+"元]");
			}
			if(amount.compareTo(new BigDecimal(coin.getMinAmount())) < 0){
				return Result.error("提现金额没有达到下限["+coin.getMinAmount().doubleValue()/100+"元]");
			}
			lock.lock();
			
			//验证账户余额
			Integer cardholder = null;
			if(CrmAcctType.ENTERPRISE.value.equals(user.getAcctType())){
				cardholder = user.getId();
			}else if(CrmAcctType.DEALER.value.equals(user.getAcctType())){
				cardholder = user.getId();
			}else if(CrmAcctType.TERMINAL_SHOP.value.equals(user.getAcctType())){
				cardholder = user.getTerminalShopId();
			}
			Integer dealerId = cardholder;
			
			BigDecimal total = disRebateDetailDao.findTotalRebateByDealerId(dealerId);
			if(total == null || amount.compareTo(total.multiply(new BigDecimal(100))) > 0) return Result.error("账户余额不足");
//			RedPacketDto packetDto = feignClientManager.findRedPacket(coin.getRedPacketId());
//			if(CommonUtils.isEmpty(packetDto))return Result.FAILURE("没有查询到红包");
			//先记账再发红包，如果发送红包失败，抛出异常，事务回滚
			DisRebateDetail rebateDetail = new DisRebateDetail();
			rebateDetail.setApplicantName(SessionUtils.getName());
			rebateDetail.setCellphoneNum(SessionUtils.getPhoneNumber());
			rebateDetail.setDealerId(dealerId);
			rebateDetail.setRebateAmount(amount.multiply(new BigDecimal(-0.01)).setScale(2, BigDecimal.ROUND_HALF_UP));//取现金额为负数
			rebateDetail.setRebateType(Constants.REBATE_TYPE_IMMEDIATE);
			rebateDetail.setDrawCashUserId(SessionUtils.getUserId());
			rebateDetail.setDrawCashOpenId(acct.getOpenId());
			rebateDetail.setRebateTime(new Date());
			rebateDetail.setDealerType(RebateTarget.SALES_MAN.value);//中粮只有业务员零钱包
			Integer detailId = insertSelective(rebateDetail);
			Assert.notNull(detailId, "更新零钱包失败");
			//发红包
			WechatRedPacketDto redPacket = new WechatRedPacketDto();
			redPacket.setAppId(coin.getToAppId());//公众号ID
//			redPacket.setConsumeMchId(packetDto.getNickName());//资金授权商户号
			redPacket.setOpenId(acct.getOpenId());//用户openId
			redPacket.setRedPacketId((long)coin.getRedPacketId());//红包参数ID
//			redPacket.setRiskInfo(riskInfo);//wechat端活动信息
//			redPacket.setSceneId(sceneId);//发红包使用场景，大于2--
			redPacket.setTotalAmount(amount.intValue());//金额
			redPacket.setTotalNum(1);//红包总数
			redPacket.setWechatRedPacketType(Constants.RED_PACKET_TYPE_COMMON);//
			
			redPacket.setEseId(enterprise.getBasicModuleId());
			redPacket.setScenceName(6);
			redPacket.setServiceName(seviceName);
			
			WechatRedPacketSendingResponse response = feignClientManager.sendRedPacket(redPacket);
			if(CommonUtils.isNotEmpty(response) && "SUCCESS".equals(response.getResultCode())){
				//只能先保存再更新，否则发送红包以后，保存失败，不能退回红包
				rebateDetail = new DisRebateDetail(); 
				rebateDetail.setMerchantBillNo(response.getMerchantBillNo());
				rebateDetail.setMerchantId(response.getMerchantId());
				rebateDetail.setId(detailId);
				updateSelective(rebateDetail);
				return Result.ok(response);
			}else{
				logger.error("发送红包参数：openId："+acct.getOpenId()+"，金额："+amount.longValue());
				throw new MessageException(response.getErrCodeDes());
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}finally{
			//如果验证失败，去释放锁，并且当前线程没有计数器，去释放锁会抛异常
			try{
				lock.unlock();
			}catch(IllegalMonitorStateException ie){
				
			}
		}
	}

	@Override
	public Integer save(DisRebateAudit audit) {
		DisRebateDetail detail = new DisRebateDetail();
		detail.setDealerId(audit.getDealerId());
		detail.setDealerType(audit.getDealerType());
		detail.setRebateAmount(audit.getAmount());
		detail.setRebateTime(new Date());
		detail.setRebateType(Constants.REBATE_TYPE_IMMEDIATE);
		return insertSelective(detail);
	}


	@Override
	public RebateList rebateList(Integer dealerId, Short dealerType,int pageNo, int pageSize) {
		RebateList draw = new RebateList();
		Page<RebateList.Detail> list = disRebateDetailDao.rebateList(dealerId,dealerType,pageNo,pageSize);
		AccumulatedRebate rebate = disRebateDetailDao.statistic(dealerId, dealerType);
		BeanUtils.copyProperties(rebate, draw);
		draw.setRebateDetail(list);
		return draw;
	}
}
